﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Remoting;
using System.Text;
using System.Xml.Linq;
using System.Web;
using com.cruxomatic.configuration.DTOs;
using com.cruxomatic.configuration.Enums;
using com.cruxomatic.configuration.FeatureManager;
using com.cruxomatic.security.EncryptionAndHashing.Enums;
using com.cruxomatic.DTOs.Configuration;
using System.Xml.Schema;

namespace com.cruxomatic.configuration
{
    public class CruxConfigurationManager
    {
        //TODO: Cache this file instead of reading from IO each time for faster access.
        //TODO: Doing this as static might not effect the changes and allow them to
        //happen independently.
        public static string GetConfigurationFolderName()
        {
            return System.Configuration.ConfigurationManager.AppSettings["SiteConfigurationDirectory"];
        }

       
        private static List<ViewInformation> GetViews()
        {
            List<ViewInformation> views = (List<ViewInformation>)HttpRuntime.Cache.Get("views");
            if (views == null)
            {
                views = new List<ViewInformation>();
                XDocument cruxConfigurationDocument = LoadConfigurationDocument();
                IEnumerable<XElement> viewNodes = cruxConfigurationDocument.Element("CruxConfigurations").Element(
                    "UserInterface")
                    .Element("Views").Elements("View");
                foreach (XElement viewNode in viewNodes)
                {
                    string viewname = viewNode.Attribute("Name").Value;
                    ViewInformation viewInformation = new ViewInformation();
                    viewInformation.ViewName = viewNode.Attribute("Name").Value;
                    viewInformation.ViewTitle = viewNode.Attribute("Title").Value;
                    viewInformation.IsInternal = bool.Parse(viewNode.Attribute("InternalView").Value);

                    viewInformation.IsDashboard = IsDashboard(viewNode);
                    if (viewInformation.IsDashboard)
                    {

                        viewInformation.DashboardName = GetDashboardName(viewNode);
                        viewInformation.ViewUrl = @"/Common/DefaultDashboard.aspx";
                    }
                    else
                    {
                        viewInformation.DashboardName = null;
                        viewInformation.ViewUrl = GetViewURL(viewNode);
                    }

                    viewInformation.ViewImageUrl = viewNode.Attribute("ImageUrl") == null
                                                       ? null
                                                       : viewNode.Attribute("ImageUrl").Value;

                    if (viewInformation.IsInternal)
                    {
                        viewInformation.ViewUrl = GetApplicationPath() + viewInformation.ViewUrl;
                        viewInformation.ViewImageUrl = GetApplicationPath() + viewInformation.ViewImageUrl;
                    }
                    if (viewNode.Attribute("Section") != null)
                        viewInformation.ViewSection = viewNode.Attribute("Section").Value;

                    viewInformation.RoleConfigurationInformation = GetRoleInformationForView(viewname);
                    views.Add(viewInformation);
                }
            }
            return views;
        }

        public static ViewInformation GetViewInformation(string ViewName)
        {
            return GetViews().SingleOrDefault(p=>p.ViewName == ViewName);
            
        }

        private static bool IsDashboard(XElement ViewNode)
        {
            if (ViewNode.Attribute("URL") != null && !string.IsNullOrEmpty(ViewNode.Attribute("URL").Value))
                return false;
            else
                return true;
        }

        private static string GetDashboardName(XElement ViewNode)
        {

            string dashboardName = string.Empty;
            string viewName = ViewNode.Attribute("Name").Value;
            if (ViewNode.Attribute("DashboardName") != null && !string.IsNullOrEmpty(ViewNode.Attribute("DashboardName").Value))
                dashboardName = ViewNode.Attribute("DashboardName").Value;

            //TODO: Move this to configuration.
            if (ViewNode.Attribute("URL") != null)
                throw new Exception("A view can not have both dashboard and url.");
            return dashboardName;
        }

        private static string GetViewURL(XElement ViewNode)
        {
            
            string url = string.Empty;
            string viewName = ViewNode.Attribute("Name").Value;
            if (ViewNode.Attribute("URL") != null && !string.IsNullOrEmpty(ViewNode.Attribute("URL").Value))
                url = ViewNode.Attribute("URL").Value;

            //TODO: Move this to configuration.
            if (ViewNode.Attribute("DashboardName") != null)
                throw new Exception("A view can not have both dashboard and url.");
            return url;
        }

        public static PasswordStorageType GetPasswordStorageType()
        {
            XDocument curxConfigurationDocument = LoadConfigurationDocument();
            string passwordStorageTypeText = curxConfigurationDocument.Element("CruxConfigurations")
                                         .Element("Security").Element("PasswordStorage")
                                         .Element("Password").Attribute("StorageType")
                                         .Value.ToLower();
            PasswordStorageType passwordStorageType =
                (PasswordStorageType)Enum.Parse(typeof(PasswordStorageType), passwordStorageTypeText);
            return passwordStorageType;
            
        }

        public static string GetSavedMasterPassword()
        {
            XDocument curxConfigurationDocument = LoadConfigurationDocument();
            string storedPasswordText = "";
            XElement passwordElement = curxConfigurationDocument.Element("CruxConfigurations")
                                         .Element("Security").Element("PasswordStorage")
                                         .Element("MasterPassword");
            if (passwordElement != null)
                storedPasswordText = passwordElement.Attribute("Value").Value;
            return storedPasswordText;

        }
        public static string GetViewTitle(string ViewName)
        {
            return GetViewInformation(ViewName).ViewTitle;
        }

        public static string GetApplicationPath()
        {
            XDocument cruxConfigurationDocument = LoadConfigurationDocument();
              return  cruxConfigurationDocument.Element("CruxConfigurations")
                  .Element("ApplicationSettings")
                  .Element("GeneralSettings")
                  .Element("ApplicationPath").Attribute("URL").Value;
        }

        public static string GetApplicationThemeName()
        {
            XDocument cruxConfigurationDocument = LoadConfigurationDocument();
            return cruxConfigurationDocument.Element("CruxConfigurations")
                .Element("ApplicationSettings")
                .Element("GeneralSettings")
                .Element("ApplicationTheme").Attribute("Name").Value;
        }

        public static string GetCruxDBConnectionString()
        {
            XDocument cruxConfigurationDocument = LoadConfigurationDocument();
            return cruxConfigurationDocument.Element("CruxConfigurations")
                .Element("ApplicationSettings")
                .Element("DatabaseSettings")
                .Element("CruxDB").Attribute("ConnectionString").Value;
        }

        public static string GetCruxApplicationLogDBConnectionString()
        {
            XDocument cruxConfigurationDocument = LoadConfigurationDocument();
            return cruxConfigurationDocument.Element("CruxConfigurations")
                .Element("ApplicationSettings")
                .Element("DatabaseSettings")
                .Element("ApplicationLogDB").Attribute("ConnectionString").Value;
        }

        public static string GetAdditionalDatabaseConnectionString(string DatabaseConnectionName)
        {
            
            XDocument cruxConfigurationDocument = LoadConfigurationDocument();
            string connectionString =   cruxConfigurationDocument.Element("CruxConfigurations")
                                        .Element("ApplicationSettings")
                                        .Element("DatabaseSettings")
                                        .Element("AdditionalDatabaseConnections")
                                        .Elements("DatabaseConnection")
                                        .Single(p => p.Attribute("Name").Value == DatabaseConnectionName)
                                        .Attribute("ConnectionString").Value;
            return connectionString;

        }

        public static bool SupportCompanyRepresentatives()
        {
            IFeatureManager featureManager = FeatureManagerFactory.GetFeatureManager();
            return featureManager.IsFeatureSupported("CompanyRepresentatives");
        }

        public static bool SupportLocationRepresentatives()
        {
            IFeatureManager featureManager = FeatureManagerFactory.GetFeatureManager();
            return featureManager.IsFeatureSupported("LocationRepresentatives");
        }

        public static string GetClassDetailsForSecurityManager(string SecurityManagerName)
        {
            ViewInformation viewInformation = new ViewInformation();
            XDocument cruxConfigurationDocument = LoadConfigurationDocument();
            XElement viewNode = cruxConfigurationDocument.Element("CruxConfigurations")
                                         .Element("Security").Element("Providers").Elements("SecurityProvider")
               .Single(p=>p.Attribute("Name").Value=="CruxSecurityProvider");
            string ClassDetails = viewNode.Attribute("Type").Value;
            return ClassDetails;
        }


        public static List<GridExtensionButtonInformation> GetExtensionInformation(string GridName)
        {
            XDocument cruxConfigurationDocument = LoadConfigurationDocument();
            XElement extensionsnode = cruxConfigurationDocument.Element("CruxConfigurations")
                                                .Element("UserInterface").Element("GridExtensions");
            List<GridExtensionButtonInformation> extensionlist = new List<GridExtensionButtonInformation>();
            if (extensionsnode != null)
            {
                IEnumerable<XElement> extensionnodes = extensionsnode.Elements("GridExtension")
                    .Where(p => p.Attribute("GridName").Value == GridName);
                foreach (XElement extensionnode in extensionnodes)
                {
                    GridExtensionButtonInformation listitem = new GridExtensionButtonInformation();
                    listitem.GridName = extensionnode.Attribute("GridName").Value;
                    listitem.ActionURL = extensionnode.Attribute("ActionLink").Value;
                    listitem.Tooltip = extensionnode.Attribute("Tooltip").Value;
                    listitem.Image = extensionnode.Attribute("Image").Value;
                    extensionlist.Add(listitem);
                }
            }
            return extensionlist;
        }
        public static NavigationInformation GetNavigationInformation(string NavigationItemName)
        {
            NavigationInformation navigationInformation = new NavigationInformation();
            XDocument cruxConfigurationDocument = LoadConfigurationDocument();
            XElement navigationNode = cruxConfigurationDocument.Element("CruxConfigurations")
                                                .Element("UserInterface").Element("Navigations").Elements("Navigation")
                .Single(p => p.Attribute("Name").Value == NavigationItemName);
            
            navigationInformation.NaviagtionItemName = navigationNode.Attribute("Name").Value;
            navigationInformation.NavigationItemDescription = navigationNode.Attribute("Description").Value;
            
            //TODO: Move this to configuration.
            string viewName = navigationNode.Attribute("ViewName").Value;
            navigationInformation.ConnectedViewName = viewName;
            ViewInformation viewInformation = GetViewInformation(viewName);
            navigationInformation.ConnectedSectionName = viewInformation.ViewSection;

            navigationInformation.ConnectedViewURL = viewInformation.ViewUrl;
            if (viewInformation.IsDashboard)
            {
                navigationInformation.ConnectedViewURL = navigationInformation.ConnectedViewURL + "?dashboard=" + viewInformation.DashboardName;
            }

            navigationInformation.NavigationItemSortOrder = int.Parse(navigationNode.Attribute("SortOrder").Value);
            navigationInformation.IsNavigationViewInternal = viewInformation.IsInternal;
                navigationInformation.RoleConfigurationInformation =
                GetRoleInformationForView(viewName);
            return navigationInformation;
        }

        public static List<NavigationInformation> GetAllNavigationItems()
        {
            List<NavigationInformation> navigationInformations = new List<NavigationInformation>();
            XDocument cruxConfigurationDocument = LoadConfigurationDocument();
            IEnumerable<XElement> navigationItems = cruxConfigurationDocument.Element("CruxConfigurations")
                .Element("UserInterface").Element("Navigations").Elements("Navigation");
            //TODO: This doesn't work with IEnumerable. The For Loop Runs N-1 times for a count of N.
            //Converted to List To Evaluate N.
            List<XElement> listofNavigationItems = navigationItems.ToList();
            foreach (XElement navigationItem in listofNavigationItems)
            {
                NavigationInformation navigationInformation = new NavigationInformation();
                string NavigationItemName = navigationItem.Attribute("Name").Value;
                navigationInformation = GetNavigationInformation(NavigationItemName);
                navigationInformations.Add(navigationInformation);
            }
            return navigationInformations;
        }
        
        
        public static ErrorInformation GetErrorInformation(string ErrorNameOrCode)
        {
            XDocument cruxConfigurationDocument = LoadConfigurationDocument();
            XElement errorNode = cruxConfigurationDocument.Element("CruxConfigurations")
                                         .Element("ExceptionsAndErrors")
                                         .Element("Errors")
                                         .Elements("Error")
                                         .SingleOrDefault(p => p.Attribute("NameOrCode").Value == ErrorNameOrCode);

            ErrorInformation errorInformation = new ErrorInformation();
            errorInformation.ErrorNameOrCode = errorNode.Attribute("NameOrCode").Value;
            errorInformation.ErrorDescription = errorNode.Attribute("Description").Value;
            errorInformation.ProbableCause = errorNode.Attribute("ProbableCause").Value;
            errorInformation.RecommendedAction = errorNode.Attribute("RecommendedAction").Value;
            errorInformation.ShortDescription = errorNode.Attribute("ShortDescription").Value;
            return errorInformation;
        }

        public static object GetProcessor(string processName)
        {
            XDocument cruxConfigurationDocument = LoadConfigurationDocument();

            XElement parentNode = cruxConfigurationDocument.Element("CruxConfigurations")
                    .Element("ProcessorSettings");
            if (parentNode != null)
            {
                XElement node = parentNode.Elements("processor")
                     .SingleOrDefault(p => p.Attribute("Name").Value == processName);
                if (node != null)
                {
                    string assemblyName = node.Attribute("Assembly").Value; //dll/exe name
                    string typeName = node.Attribute("Type").Value;

                    string binPath = HttpContext.Current.Request.PhysicalApplicationPath + @"bin\" + assemblyName;
                    ObjectHandle obj = null;
                    obj = Activator.CreateInstanceFrom(binPath, typeName);
                    if (obj != null) return obj.Unwrap();
                }
            }

            return null;
        }

        public static string GetApplicationDefaultView()
        {
            ViewInformation viewInformation = new ViewInformation();
            XDocument cruxConfigurationDocument = LoadConfigurationDocument();
            XAttribute defaultViewName= cruxConfigurationDocument.Element("CruxConfigurations").Element("UserInterface")
                                         .Element("DefaultView").Attribute("ViewName");
            return defaultViewName.Value;
            
        }

        public static List<ViewInformation> GetAllInternalView(string sectionName)
        {
            List<ViewInformation> views = new List<ViewInformation>();
            XDocument cruxConfigDoc = LoadConfigurationDocument();
            IEnumerable<XElement> xViews = (cruxConfigDoc.Element("CruxConfigurations").Element("UserInterface")
                .Element("Views").Elements("View")
                .Where(v => v.Attribute("Section") != null))
                .Where(v => v.Attribute("Section").Value == sectionName && v.Attribute("InternalView").Value == "true");
            ViewInformation view;
            foreach (XElement xView in xViews)
            {
                view = GetViewInformation(xView.Attribute("Name").Value);
                views.Add(view);
            }
            return views;
        }

      
        public static DashboardInformation GetDashboard(string dashboardName)
        {
            DashboardInformation dashboard = new DashboardInformation();
            List<DashboardItemInformation> dashboardItems = new List<DashboardItemInformation>();
            XElement xDashboard = null; 

            XDocument cruxConfigurationDocument = LoadConfigurationDocument();
            XElement xDashBoardsNode = cruxConfigurationDocument.Element("CruxConfigurations").Element("UserInterface")
                                       .Element("Dashboards");
            if(xDashBoardsNode!=null)
                xDashboard = xDashBoardsNode.Elements("Dashboard")
                             .SingleOrDefault(p => p.Attribute("Name").Value == dashboardName);

            if (xDashboard != null)
            {
                dashboard.Title = xDashboard.Attribute("Name").Value;
                dashboard.DasboardItems = GetAllDashboardItems(xDashboard);
            }
            return dashboard;
        }


        public static List<ApplicationCustomSetting> GetApplicationCustomSettings()
        {
            XDocument cruxConfigurationDocument = LoadConfigurationDocument();
            var settings = (from a in cruxConfigurationDocument.Element("CruxConfigurations")
                        .Element("ApplicationSettings")
                        .Element("CustomSettings")
                        .Elements("Add")
                            select new ApplicationCustomSetting { Key = a.Attribute("Key").Value, Value = a.Attribute("Value").Value });
            return settings == null ? null : settings.ToList();
        }

        public static ApplicationCustomSetting GetApplicationCustomSetting(string key)
        {
             List<ApplicationCustomSetting> settings = GetApplicationCustomSettings();
             if (settings == null)
                 return null;
             else
             {
                 IEnumerable<ApplicationCustomSetting> filteredSettings = settings.Where(s => s.Key == key);
                 if (filteredSettings != null)
                 {
                     return filteredSettings.SingleOrDefault();
                 }
                 else
                 {
                     return null;
                 }
             }
        }



        private static List<DashboardItemInformation> GetAllDashboardItems(XElement xDashboard)
        {
            List<DashboardItemInformation> dashboardItems = new List<DashboardItemInformation>();
            IEnumerable<XElement> xDashboardItems = xDashboard.Element("DashboardItems").Elements("DashboardItem");
            foreach (var xDashboardItem in xDashboardItems)
            {
                dashboardItems.Add(new DashboardItemInformation
                {
                    Title = xDashboardItem.Attribute("Name").Value,
                    View = GetViewInformation(xDashboardItem.Attribute("View").Value)
                });
            }
            return dashboardItems;
        }

        private static XDocument LoadConfigurationDocument()
        {
            return ValidateAndLoadConfiguration();
        }

        private static XDocument ValidateAndLoadConfiguration()
        {
            XDocument xDocument = (XDocument)HttpRuntime.Cache.Get("CruxConfigurationFile");
            List<string> cachedconfigurationfiles = new List<string>();
            if (xDocument == null)
            {
                XmlSchemaSet schemas = new XmlSchemaSet();
                string docPath = "";
                string schemaPath = "";

                if (HttpContext.Current != null)
                {
                    docPath = HttpContext.Current.Server.MapPath("~/" + GetConfigurationFolderName() + "/Crux.config");
                    schemaPath = HttpContext.Current.Server.MapPath("~/" + GetConfigurationFolderName() + "/Crux.xsd");
                }
                else
                {
                    docPath = System.Configuration.ConfigurationManager.AppSettings["CruxConfigFolder"] + @"\Crux.config";
                    schemaPath = System.Configuration.ConfigurationManager.AppSettings["CruxConfigFolder"] + @"\Crux.xsd";
                }
                schemas.Add(string.Empty, schemaPath);
                xDocument = XDocument.Load(docPath);
                
                cachedconfigurationfiles.Add(docPath);

                IEnumerable<XElement> AppFolders = xDocument.Element("CruxConfigurations")
                .Element("UserInterface").Elements("ApplicationFolder");

                foreach (XElement appFolder in AppFolders)
                {
                    string applicationfile = GetApplicationConfigurationFileName(appFolder.Attribute("Name").Value);
                    cachedconfigurationfiles.Add(applicationfile);
                    XDocument appDocument = GetAppConfigurationDocument(appFolder.Attribute("Name").Value);
                    xDocument = MergeDocument(xDocument, appDocument);
                }

                bool errors = false;
                string exceptionMessage="Invalid Configuration.";
                xDocument.Validate(schemas, (o, e) =>
                {
                    exceptionMessage = exceptionMessage + " " + e.Exception.Message;
                    errors = true;
                });
                if (errors)
                    throw new Exception(exceptionMessage);
                else
                    CacheConfigurationDocument("CruxConfigurationFile", cachedconfigurationfiles.ToArray(),xDocument);

                List<ViewInformation> views = GetViews();
                CacheViews("views", cachedconfigurationfiles.ToArray(), views);
            }
            return xDocument;
        }

        private static void CacheViews(string name, string[] filenames, List<ViewInformation> views)
        {
            HttpRuntime.Cache.Add(name, views, new System.Web.Caching.CacheDependency(filenames), DateTime.Now.AddDays(7),
           TimeSpan.Zero, System.Web.Caching.CacheItemPriority.High, null);
        }

        private static string GetApplicationConfigurationFileName(string applicationfolder)
        {
            return HttpContext.Current.Server.MapPath("~/" + applicationfolder + "/Crux.config");
        }

        private static void CacheConfigurationDocument(string name, string[] filenames, XDocument xDocument)
        {
            HttpRuntime.Cache.Add(name, xDocument, new System.Web.Caching.CacheDependency(filenames), DateTime.Now.AddDays(7),
            TimeSpan.Zero, System.Web.Caching.CacheItemPriority.High, null);
        }

        private static XDocument GetAppConfigurationDocument(string appFolderName)
        {
                XDocument xDocument;
                string fileName = GetApplicationConfigurationFileName(appFolderName);
                xDocument = XDocument.Load(fileName);
                return xDocument;
        }

        private static XDocument MergeDocument(XDocument cruxConfigDoc, XDocument appConfigDoc)
        {
            XElement cruxUserInterface = cruxConfigDoc.Element("CruxConfigurations").Element("UserInterface");
            XElement cruxExceptionsAndErrors = cruxConfigDoc.Element("CruxConfigurations").Element("ExceptionsAndErrors");
            XElement cruxSupportedFeatures =
                cruxConfigDoc.Element("CruxConfigurations").Element("ApplicationFeatures");

            if (appConfigDoc.Element("CruxConfigurations") != null)
            {
                XElement appUserInterface = appConfigDoc.Element("CruxConfigurations").Element("UserInterface");
                XElement appExceptionsAndErrors = appConfigDoc.Element("CruxConfigurations").Element("ExceptionsAndErrors");
                XElement appApplicationFeatures =
                    appConfigDoc.Element("CruxConfigurations").Element("ApplicationFeatures");

                if (appExceptionsAndErrors != null)
                {
                    if (appExceptionsAndErrors.Element("Errors") != null)
                    {
                        IEnumerable<XElement> errors = appExceptionsAndErrors.Element("Errors").Elements("Error");
                        foreach (XElement error in errors)
                        {
                            IEnumerable<XElement> filteredExceptionsAndErrors = cruxExceptionsAndErrors
                                .Element("Errors").Elements("Error")
                                .Where(v => v.Attribute("NameOrCode").Value == error.Attribute("NameOrCode").Value);
                            if (filteredExceptionsAndErrors.Count() > 0)
                                filteredExceptionsAndErrors.FirstOrDefault().Remove();

                            cruxExceptionsAndErrors.Element("Errors").Add(error);
                        }
                    }
                }

                if (appUserInterface != null)
                {
                    if (appUserInterface.Element("Views") != null)
                    {
                        IEnumerable<XElement> views = appUserInterface.Element("Views").Elements("View");
                        foreach (XElement view in views)
                        {
                            IEnumerable<XElement> filteredViews = cruxUserInterface
                                .Element("Views").Elements("View")
                                .Where(v => v.Attribute("Name").Value == view.Attribute("Name").Value);
                            if (filteredViews.Count() > 0)
                                filteredViews.FirstOrDefault().Remove();
                            cruxUserInterface.Element("Views").Add(view);
                        }
                    }

                    if (appUserInterface.Element("Navigations") != null)
                    {
                        IEnumerable<XElement> Navs = appUserInterface.Element("Navigations").Elements("Navigation");
                        foreach (XElement nav in Navs)
                        {
                            IEnumerable<XElement> filteredNavs = cruxUserInterface
                                .Element("Navigations").Elements("Navigation")
                                .Where(v => v.Attribute("Name").Value == nav.Attribute("Name").Value);
                            if (filteredNavs.Count() > 0)
                                filteredNavs.FirstOrDefault().Remove();

                            cruxUserInterface.Element("Navigations").Add(nav);
                        }
                    }

                    if (appUserInterface.Element("GridExtensions") != null)
                    {
                        IEnumerable<XElement> Navs = appUserInterface.Element("GridExtensions").Elements("GridExtension");
                        foreach (XElement nav in Navs)
                        {
                            cruxUserInterface.Element("Navigations").Add(nav);
                        }
                    }


                    if (appUserInterface.Element("Dashboards") != null)
                    {
                        IEnumerable<XElement> dashboards = appUserInterface.Element("Dashboards").Elements("Dashboard");
                        foreach (XElement dashboard in dashboards)
                        {
                            IEnumerable<XElement> filteredDashboards = cruxUserInterface
                                .Element("Dashboards").Elements("Dashboard")
                                .Where(v => v.Attribute("Name").Value == dashboard.Attribute("Name").Value);
                            if (filteredDashboards.Count() > 0)
                            {
                                XElement xDashboard = filteredDashboards.FirstOrDefault();
                                foreach (
                                    XElement dashboardItem in
                                        dashboard.Element("DashboardItems").Elements("DashboardItem"))
                                {
                                    xDashboard.Element("DashboardItems").Add(dashboardItem);
                                }
                            }
                            else
                            {
                                cruxUserInterface.Element("Dashboards").Add(dashboard);
                            }
                        }



                    }
                    if (appApplicationFeatures != null)
                    {
                        IEnumerable<XElement> features = appApplicationFeatures.Elements("Feature");
                        foreach (XElement feature in features)
                        {
                            IEnumerable<XElement> filteredFeatures = cruxSupportedFeatures
                .Elements("Feature")
                .Where(v => v.Attribute("Name").Value == feature.Attribute("Name").Value);
                            if (filteredFeatures.Count() > 0)
                                filteredFeatures.FirstOrDefault().Remove();

                            cruxSupportedFeatures.Add(feature);
                        }
                    }
                
                }
                
            }
            return cruxConfigDoc;
        }

        private static RoleConfigurationInformation GetRoleInformationForView(string ViewName)
        {
            ViewInformation viewInformation = new ViewInformation();
            XDocument cruxConfigurationDocument = LoadConfigurationDocument();
            XElement viewNode = cruxConfigurationDocument.Element("CruxConfigurations").Element("UserInterface").Element("Views")
                .Elements("View")
                .First(p => p.Attribute("Name").Value == ViewName);

            string roleConditionValue = "";
            if (viewNode.Element("Roles").Attribute("Condition") != null)
                roleConditionValue = viewNode.Element("Roles").Attribute("Condition").Value.ToLower();

            if (roleConditionValue.Trim() == "*") roleConditionValue = Conditions.all.ToString();
            else if (roleConditionValue.Trim().ToLower() == "single") roleConditionValue = Conditions.single.ToString();
            else if (string.IsNullOrEmpty(roleConditionValue.Trim())) roleConditionValue = Conditions.none.ToString();

            RoleConfigurationInformation roleConfigurationInformation = new RoleConfigurationInformation();
            roleConfigurationInformation.RoleCondition = (Conditions)Enum.Parse(typeof(Conditions), roleConditionValue);
            IEnumerable<XElement> roleElements = viewNode.Element("Roles").Elements("Role");
            foreach (XElement role in roleElements)
            {
                roleConfigurationInformation.RoleNames.Add(role.Attribute("Name").Value);
            }

            return roleConfigurationInformation;
        }

        public static XDocument LoadConfigFile()
        {
            return LoadConfigurationDocument();
        }



        internal static string GetClassDetailsForFeatureManager(string featureProvider)
        {
            ViewInformation viewInformation = new ViewInformation();
            XDocument cruxConfigurationDocument = LoadConfigurationDocument();
            XElement viewNode = cruxConfigurationDocument.Element("CruxConfigurations")
                                         .Element("FeatureManager").Elements("FeatureProvider")
               .Single(p => p.Attribute("Name").Value == "CruxFeatureProvider");
            string ClassDetails = viewNode.Attribute("Type").Value;
            return ClassDetails;
        }

        public static string GetWorkflowFolderName()
        {
            XDocument cruxConfigurationDocument = LoadConfigurationDocument();
            XElement workflowFolderElement = cruxConfigurationDocument.Element("CruxConfigurations")
                                         .Element("ApplicationSettings")
                                         .Element("WorkflowSettings").Element("WorkflowFolder");
            string WorkflowFolderName = workflowFolderElement.Attribute("Name").Value;
            return WorkflowFolderName;
        }

        internal static string GetClassDetailsForPasswordManager(string passwordProvider)
        {
            XDocument cruxConfigurationDocument = LoadConfigurationDocument();
            XElement viewNode = cruxConfigurationDocument.Element("CruxConfigurations")
                                         .Element("PasswordManager").Elements("PasswordProvider")
               .Single(p => p.Attribute("Name").Value == passwordProvider);
            string ClassDetails = viewNode.Attribute("Type").Value;
            return ClassDetails;
        }

        public static string GetErrorMessageForPasswordManager(string passwordProvider)
        {
            XDocument cruxConfigurationDocument = LoadConfigurationDocument();
            XElement viewNode = cruxConfigurationDocument.Element("CruxConfigurations")
                                         .Element("PasswordManager").Elements("PasswordProvider")
               .Single(p => p.Attribute("Name").Value == passwordProvider);
            string ClassDetails = viewNode.Attribute("ErrorMessage").Value;
            return ClassDetails;
        }

        public static XDocument GetFullConifgurationSettings()
        {
            return LoadConfigurationDocument();
        }
    }
}
